using B.S.RbacData.Domain.Traceabilitys;
using B.S.RbacData.ErrorCode;
using B.S.RbacData.Infrastructure;
using B.S.RbacData.Write.API.Applications.Commands.Traceabilitys;
using MediatR;
using Microsoft.EntityFrameworkCore;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO.Compression;
using System.Security.Claims;
using ZXing;
using ZXing.QrCode;
using ZXing.QrCode.Internal;
using ZXing.Windows.Compatibility;

namespace B.S.RbacData.Write.API.Applications.Commandhandlters.Traceabilitys
{
    /// <summary>
    /// 导出QR码命令处理器
    /// </summary>
    public class ExportQRCodeCommandHandlter : IRequestHandler<ExportQRCodeCommand, byte[]>
    {
        private readonly DataDbcontext _dbContext;
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly ILogger<ExportQRCodeCommandHandlter> _logger;
        private readonly IConfiguration _configuration;

        /// <summary>
        /// 构造函数
        /// </summary>
        public ExportQRCodeCommandHandlter(
            DataDbcontext dbContext,
            IHttpContextAccessor httpContextAccessor,
            ILogger<ExportQRCodeCommandHandlter> logger,
            IConfiguration configuration)
        {
            _dbContext = dbContext;
            _httpContextAccessor = httpContextAccessor;
            _logger = logger;
            _configuration = configuration;
        }

        /// <summary>
        /// 处理导出QR码命令
        /// </summary>
        public async Task<byte[]> Handle(ExportQRCodeCommand request, CancellationToken cancellationToken)
        {
            try
            {
                // 验证产品是否存在
                var product = await _dbContext.Products
                    .Include(p => p.Goods)
                    .FirstOrDefaultAsync(p => p.ID == request.ProductId && !p.IsDeleted, cancellationToken);

                if (product == null)
                    throw new Exception("产品不存在");

                // 获取当前用户ID
                var userId = _httpContextAccessor.HttpContext?.User.FindFirstValue("UserId");
                if (string.IsNullOrEmpty(userId))
                    throw new Exception("未获取到用户信息");

                // 临时目录和批次号
                var tempDir = Path.Combine(Path.GetTempPath(), $"qrcodes_{Guid.NewGuid()}");
                Directory.CreateDirectory(tempDir);
                var now = DateTime.Now;
                var batchNumber = $"{product.ProductionBatch}-{now:yyyyMMddHHmmss}";
                var baseUrl = _configuration["AppSettings:TraceabilityBaseUrl"] ?? "https://trace.example.com";
                var qrCodes = new List<QRCodeModel>();

                try
                {
                    // 创建二维码生成器
                    var barcodeWriter = new BarcodeWriter<Bitmap>
                    {
                        Format = BarcodeFormat.QR_CODE,
                        Options = new QrCodeEncodingOptions
                        {
                            DisableECI = true,
                            CharacterSet = "UTF-8",
                            Width = 300,
                            Height = 300,
                            Margin = 10,
                            ErrorCorrection = ErrorCorrectionLevel.H // 高容错率
                        },
                        Renderer = new BitmapRenderer() // 设置渲染器实例
                    };

                    for (int i = 0; i < request.Quantity; i++)
                    {
                        // 生成唯一标识和URL
                        var uniqueCode = Guid.NewGuid().ToString("N");
                        var traceabilityUrl = $"{baseUrl}/traceability-detail?id={uniqueCode}";
                        
                        // 生成QR码
                        var filePath = Path.Combine(tempDir, $"{product.Goods?.GoodsName ?? "product"}_{i + 1}.png");
                        using (var bitmap = barcodeWriter.Write(traceabilityUrl))
                        {
                            // 添加文本标签
                            using (var graphics = Graphics.FromImage(bitmap))
                            using (var font = new Font("Arial", 10))
                            {
                                var scanText = "扫描查看溯源详情";
                                var scanTextSize = graphics.MeasureString(scanText, font);
                                
                                // 在底部绘制文本
                                graphics.DrawString(scanText, font, Brushes.Black,
                                    (bitmap.Width - scanTextSize.Width) / 2,
                                    bitmap.Height - scanTextSize.Height - 10);
                            }
                            
                            // 保存图像
                            bitmap.Save(filePath, ImageFormat.Png);
                        }

                        // 添加记录
                        qrCodes.Add(new QRCodeModel
                        {
                            ProductId = request.ProductId,
                            UniqueCode = uniqueCode,
                            GeneratedDate = now,
                            IsUsed = false,
                            BatchNumber = batchNumber,
                            CreateTime = now,
                            CreateUserId = int.Parse(userId),
                            IsDeleted = false
                        });
                    }

                    // 保存到数据库
                    await _dbContext.QRCodes.AddRangeAsync(qrCodes, cancellationToken);
                    await _dbContext.SaveChangesAsync(cancellationToken);

                    // 创建ZIP文件并返回
                    var zipPath = Path.Combine(Path.GetTempPath(), $"qrcodes_{Guid.NewGuid()}.zip");
                    ZipFile.CreateFromDirectory(tempDir, zipPath);
                    var zipBytes = await File.ReadAllBytesAsync(zipPath, cancellationToken);
                    
                    // 清理临时文件
                    File.Delete(zipPath);
                    Directory.Delete(tempDir, true);

                    return zipBytes;
                }
                catch
                {
                    if (Directory.Exists(tempDir))
                        Directory.Delete(tempDir, true);
                    throw;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "导出QR码时发生错误");
                throw;
            }
        }
    }
} 